#pragma once

#include "Connection.hpp"
#include "Epoller.hpp"
#include "Log.hpp"
#include "Common.hpp"
#include <memory>
#include <unordered_map>


class Reactor{
	const static int revs_num = 256;
public:
	Reactor():_epoll_ptr(std::make_unique<Epoller>()), _isrunning(false){}

	void Loop()
	{
		if(IsConnectionEmpty())
				return;

		_isrunning = true;
		while(_isrunning){
			int num = LoopOnce(-1);
			if(num > 0){
				Dispatch(num);
			}
		}
	}

	bool IsConnectionEmpty(){
		return _connections.empty();
	}

	int LoopOnce(int timeout){
		return _epoll_ptr->WaitEvent(_revs, revs_num, timeout);
	}

	void Stop(){
		_isrunning = false;
	}

	void Dispatch(int num){ 
		for(int i = 0; i < num; i++){
			int sockfd = _revs[i].data.fd;
			uint32_t revents = _revs[i].events;
			if(revents & EPOLLERR || revents & EPOLLHUP){
				// 异常事件
				_connections[sockfd]->Excepter();
			}
			else if(revents & EPOLLIN){
				// 可读事件
				_connections[sockfd]->Recever();
			}
			else if(revents & EPOLLOUT){
				// 可写事件
				_connections[sockfd]->Sender();
			}

		}
	}

	// 添加新连接
	void AddConnection(std::shared_ptr<Connection> conn){
		int sockfd = conn->GetSockFd();
		uint32_t events = conn->GetEvent();
		if(IsConnectionExists(sockfd))
			return;

		// 注册到epoll
		_epoll_ptr->AddEvent(sockfd, events);
		// 绑定Reactor所属
		conn->SetOwner(this);
		// 添加到连接管理池
		_connections[sockfd] = conn;
	}

	// 修改连接行为
	void EnableReadWrite(int sockfd, bool enableread, bool enablewrite){
		if(!IsConnectionExists(sockfd))
			return;

		uint32_t new_events = EPOLLET | (enableread ? EPOLLIN : 0) | (enablewrite ? EPOLLOUT : 0);
		_connections[sockfd]->SetEvents(new_events);
		_epoll_ptr->ModEventHelper(EPOLL_CTL_MOD, sockfd, new_events);
	}

	// 删除连接
	void DelConnection(int sockfd){
		if(!IsConnectionExists(sockfd))
			return;

		_epoll_ptr->DelEvent(sockfd, _connections[sockfd]->GetEvent());
		_connections.erase(sockfd);
		close(sockfd);
	}


	bool IsConnectionExists(int sockfd){
		return IsConnectionExistsHelper(sockfd);
	}

	bool IsConnectionExists(const std::shared_ptr<Connection> &conn){
		return IsConnectionExistsHelper(conn->GetSockFd());
	}

private:
	// 管理epoll实例
	std::unique_ptr<Epoller> _epoll_ptr;
	// 管理连接,key是连接的sockfd, value是连接对象
	std::unordered_map<int, std::shared_ptr<Connection>> _connections;
	// 就绪事件数组
	struct epoll_event _revs[revs_num];
	// 运行标注
	bool _isrunning;

	bool IsConnectionExistsHelper(int sockfd){
		return _connections.find(sockfd) != _connections.end();
	}
};